//实现项目中一些公共的工具类接口
//1. 生成一个唯一ID的接口
//2. 文件的读写操作接口

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <atomic>
#include <random>
#include <iomanip>
#include "logger.hpp"
namespace zzy_mims
{
    std::string uuid()
    {
        //生成一个由16位随机字符组成的字符串作为唯一ID
        // 1. 生成6个0~255之间的随机数字(1字节-转换为16进制字符)--生成12位16进制字符
        std::random_device rd;//实例化设备随机数对象-用于生成设备随机数
        std::mt19937 generator(rd());//以设备随机数为种子，实例化mt19937随机数生成器对象
        std::uniform_int_distribution<int> distribution (0,255);//限定数据范围

        std::stringstream ss;
        for(int i = 0;i<6;i++)
        ss<<std::setw(2)<<std::setfill('0')<<std::hex<<distribution(generator);
        //2. 通过一个静态变量生成一个2字节的编号数字--生成4位16进制数字字符
        ss<<"-";
        static std::atomic<unsigned short> idx(0);
        unsigned short tmp = idx.fetch_add(1);
        ss<<std::setw(4)<<std::setfill('0')<<std::hex<<tmp;
        return ss.str();
    }
    std::string vcode()
    {
        std::random_device rd;//实例化设备随机数对象-用于生成设备随机数
        std::mt19937 generator(rd());//以设备随机数为种子，实例化mt19937随机数生成器对象
        std::uniform_int_distribution<int> distribution (0,9999);//限定数据范围

        std::stringstream ss;
        ss<<std::setw(4)<<std::setfill('0')<<distribution(generator);
        return ss.str();
    }
    bool readFile(const std::string& filename,std::string& body)
    {
        //将filename文件中的数据读到body中
        std::ifstream ifs(filename,std::ios::binary|std::ios::in);
        if(ifs.is_open()==false)
        {
            LOG_ERROR("{}文件打开失败\n",filename);
            return false;
        }
        //seekg(偏移量,基准点)
        ifs.seekg(0,std::ios::end);//跳转到文件末尾
        size_t flen = ifs.tellg();//获取当前偏移量也就是文件大小
        ifs.seekg(0,std::ios::beg);//跳转到文件起始
        body.resize(flen);
        ifs.read(&body[0],flen);
        if(ifs.good()==false)
        {
            LOG_ERROR("{}文件读取失败\n",filename);
            ifs.close();
            return false;
        }
        ifs.close();
        return true;
    }
    bool writeFile(const std::string& filename,const std::string& body)
    {
        //将body中的数据写入filename文件中
        std::ofstream ofs(filename,std::ios::binary|std::ios::out|std::ios::trunc);//trunc表示覆盖式写入
        if(ofs.is_open()==false)
        {
            LOG_ERROR("{}文件打开失败\n",filename);
            return false;
        }
        ofs.write(body.c_str(),body.size());
        if(ofs.good()==false)
        {
            LOG_ERROR("{}文件写入失败\n",filename);
            ofs.close();
            return false;
        }
        ofs.close();
        return true;
    }
}